/**
 * hnjz.com Inc.
 * Copyright (c) 2004-2011 All Rights Reserved.
 */
package com.hnjz.common.filter;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.hnjz.common.Profiler;

/**
 * 该过滤器处理以下问题：
 * 
 * @author wumi
 * @version $Id: AppFilter.java, v 0.1 Dec 29, 2011 6:19:50 AM Administrator Exp $
 */
public class AppFilter implements Filter {

    /**日志*/
    private static final Log    log              = LogFactory.getLog(AppFilter.class);

    private static final String DEFAULT_ENCODING = "GBK";

    private String              encoding;

    private int                 duration_        = 2000;

    /**
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    public void doFilter(ServletRequest sreq, ServletResponse res, FilterChain chain)
                                                                                     throws IOException,
                                                                                     ServletException {
        HttpServletRequest req = (HttpServletRequest) sreq;
        // 开始处理request, 并计时.
        String requestString = dumpRequest(req);
        Profiler.start("process HTTP request");
        try {
            req = new HttpServletRequestWrapperTrim(req);
            req.setCharacterEncoding(encoding);
            chain.doFilter(req, res);
        } finally {
            Profiler.release();
            long duration = Profiler.getDuration();
            String detail = Profiler.dump("Detail: ", "        ");
            if (duration > duration_) {
                log.error(MessageFormat.format("Response of {0} returned in {1,number}ms\n{2}\n",
                    new Object[] { requestString, new Long(duration), detail }));
            }
            Profiler.reset();
        }

    }

    /**
     * 取得request的内容(HTTP方法, URI)
     *
     * @param request HTTP请求
     *
     * @return 字符串
     */
    protected String dumpRequest(ServletRequest request) {
        HttpServletRequest req = (HttpServletRequest) request;
        StringBuilder buffer = new StringBuilder(req.getMethod());
        buffer.append(" ").append(req.getRequestURI());
        String queryString = req.getQueryString();
        if (queryString != null) {
            buffer.append("?").append(queryString);
        }
        return buffer.toString();
    }

    /**
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    public void init(FilterConfig config) throws ServletException {
        encoding = config.getInitParameter("encoding");
        if (StringUtils.isBlank(encoding)) {
            encoding = DEFAULT_ENCODING;
        }
        if (StringUtils.isNotBlank(config.getInitParameter("duration"))) {
            duration_ = Integer.parseInt(config.getInitParameter("duration"));
        }
        if (log.isDebugEnabled()) {
            log.debug("encoding:" + encoding);
            log.debug("duration_:" + duration_);
        }
    }

    /**
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
    }

    /**
     * 将参数统一trim
     * 
     * @author wumi
     * @version $Id: MoHandlerInterceptor.java, v 0.1 Jul 29, 2013 4:35:46 PM wumi Exp $
     */
    private class HttpServletRequestWrapperTrim extends HttpServletRequestWrapper {
        
        @SuppressWarnings("unchecked")
        public HttpServletRequestWrapperTrim(HttpServletRequest request) {
            super(request);
            if (log.isDebugEnabled()) {
             
                Enumeration<String> s = request.getHeaderNames();
                while (s.hasMoreElements()) {
                    String o = s.nextElement();
                    log.debug(o + ":" + request.getHeader(o));
                }
            }
        }

        /**
         * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
         */
        public String getParameter(String name) {
            return StringUtils.trim(super.getParameter(name));
        }

        /**
         * @see javax.servlet.ServletRequestWrapper#getParameterValues(java.lang.String)
         */
        public String[] getParameterValues(String name) {
            String[] re = super.getParameterValues(name);
            if (null == re) {
                return re;
            }
            for (int i = 0; i < re.length; i++) {
                re[i] = StringUtils.trim(re[i]);
            }
            return re;
        }

    }

}
